package utils

import (
	"a-common/config"
	"fmt"
	"github.com/jaevor/go-nanoid"
	"log"
	"strconv"
	"sync"
	"time"

	"github.com/yitter/idgenerator-go/idgen"
)

var (
	idUtilsTemp *IdUtils
	idUtilsOnce sync.Once
)

type IdUtils struct{}

func NewIdUtils() *IdUtils {
	idUtilsOnce.Do(func() {
		idUtilsTemp = &IdUtils{}
	})
	return idUtilsTemp
}

// 初始化全局ID
func init() {
	// workerId 每个应用必须唯一
	// workerId := uint16(1)
	workerId := config.Config.Server.ServerId
	// 创建 IdGeneratorOptions 对象，可在构造函数中输入 WorkerId：
	var options = idgen.NewIdGeneratorOptions(workerId)
	// options.WorkerIdBitLength = 10  // 默认值6，限定 WorkerId 最大值为2^6-1，即默认最多支持64个节点。
	// options.SeqBitLength = 6; // 默认值6，限制每毫秒生成的ID个数。若生成速度超过5万个/秒，建议加大 SeqBitLength 到 10。
	// options.BaseTime = Your_Base_Time // 如果要兼容老系统的雪花算法，此处应设置为老系统的BaseTime。
	// ...... 其它参数参考 IdGeneratorOptions 定义。
	// 保存参数（务必调用，否则参数设置不生效）：
	idgen.SetIdGenerator(options)
}

// GetNanoId 替代UUID
func (m *IdUtils) GetNanoId() string {
	gen, err := nanoid.Canonic()
	if err != nil {
		return ""
	}
	id1 := gen()
	//log.Printf("ID 1: %s", id1) // eLySUP3NTA48paA9mLK3V
	return id1
}

// GetNanoIdNum 替代UUID
func (m *IdUtils) GetNanoIdNum() string {
	// Makes sense to use CustomASCII since 0-9 is ASCII.
	decenaryID, err := nanoid.CustomASCII("0123456789", 12)
	if err != nil {
		return ""
	}
	id2 := decenaryID()
	//log.Printf("ID 2: %s", id2) // 817411560404
	return id2
}

// GetXhId 获取雪花飘移算法ID
func (m *IdUtils) GetXhId() int64 {
	return idgen.NextId()
}

// CreateOrderId 获取订单ID
// 创建订单ID规则，默认每分钟内订单不会超过1w单，固定长度16位
// 订单规则：开头标识符号(2位) + 年月日时分(10位) + redis自增Id(4位)
func (m *IdUtils) CreateOrderId(preKey int) int64 {
	if preKey > 99 || preKey < 10 {
		log.Printf("开头标识符不符合规范")
		return 0
	}
	// 获取当前时间 YYMMDDHHmmss
	now := time.Now()
	yearStr := fmt.Sprintf("%02d", now.Year()%100)
	monthStr := fmt.Sprintf("%02d", now.Month()+1)
	dayStr := fmt.Sprintf("%02d", now.Day())
	hourStr := fmt.Sprintf("%02d", now.Hour())
	minuteStr := fmt.Sprintf("%02d", now.Minute())
	// secondStr := fmt.Sprintf("%02d", now.Second())
	// 获取redis自增Id
	id, err := rdCli.Incr("order:incr:id", 60)
	if err != nil {
		log.Println(err.Error())
		return 0
	}
	idStr := fmt.Sprintf("%04d", id)
	uId, err := strconv.ParseInt(strconv.Itoa(preKey)+yearStr+monthStr+dayStr+hourStr+minuteStr+idStr, 10, 64)
	if err != nil {
		log.Println(err.Error())
		return 0
	}
	return uId
}
